home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
ssedsrc.arc
/
SSED.C
next >
Wrap
Text File
|
1985-12-11
|
9KB
|
430 lines
#define VERSION "ssed.c 2.2.1 DeSmet 5/20/84\n"
/*
* (small/stupid) Stream Editor
* Accepts a,c,d,i commands only
* commands are on standard input
* old file is specified
* edited result is specified file
* Line numbers are decimal, . and $
* Modified for DeSmet by Tom Bonfield
*
* Chuck Forsberg
* Omen Technology Inc
* Rt 1 Box 120v Portland OR 97231
* Compuserve: 70715,131
*
*/
/* system dependent stuff */
#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define ERROR (-1)
#define CPMEOF 032
#define MAXINT 32000
FILE in, out;
#define HUGELINE 1024 /* much easier than crashing if line is too long */
char *aname; /* name of antecedent file */
char *oname; /* name of resultant file */
int linno; /* number of lines that have been output */
int op1,op2; /* first and (possibly same) last line of cmd */
char crcseen; /* TRUE if crc given in command line */
unsigned cmdcrc; /* crc value encountered (decimal) in command line */
unsigned crc; /* accumulated crc(k) of copied lines from old file */
char cmd, cmdline[HUGELINE],insline[HUGELINE], *axin;
char Verbose,Unsqueeze, Ignore;
char cmdeof; /* EOF (cpmeof) seen on command input */
char ineof; /* EOF (cpmeof) seen on file input */
xgetchar()
{
return fgetc(stdin);
}
int getcr();
int getcin();
int (*getthis)(); /* getchar function for current file */
/* Definitions and externals for unsqueezer function */
#define RECOGNIZE 0xFF76 /* unlikely pattern */
/* External declarations for USQ feature */
#define NUMVALS 257 /* 256 data values plus SPEOF*/
/* Decoding tree */
struct {
int children[2]; /* left, right */
} dnode[NUMVALS - 1];
int bpos; /* last bit position read */
int curin; /* last byte value read */
/* Variables associated with repetition decoding */
int repct; /*Number of times to return value*/
int value; /*current byte value or EOF */
int inch;
getcin()
{
return getc(in);
}
main(argc, argv)
char **argv;
{
char *cp;
getthis=getcin;
Verbose=Ignore=Unsqueeze=FALSE;
while (--argc && *(cp = *++argv)=='-') {
while( *++cp) {
switch(tolower(*cp)) {
case 'i':
Ignore++; break;
case 'u':
Unsqueeze++; break;
case 'v':
Verbose++; break;
default:
break;
}
}
}
if(argc != 2) {
fprintf(stderr,VERSION);
fprintf(stderr,"Usage: ssed [-iuv] infile outfile [<cmdfile]\n");
fprintf(stderr,"\tEditing commands on stdin\n");
fprintf(stderr,"\t-i Ignore CRC errors\n");
fprintf(stderr,"\t-u Unsqueeze infile\n");
fprintf(stderr,"\t-v Verbose\n");
exit(1);
}
if((in=fopen( aname=argv[0], "r")) == NULL) {
fprintf(stderr, "Can't open %s", aname);
exit(1);
}
if((out=fopen( oname=argv[1], "w")) == NULL) {
fprintf(stderr, "Can't open %s", oname);
exit(2);
}
if(Unsqueeze) {
getthis=getcr; /* switch getchar function */
init_usq(); /* initialize unpacking */
}
linno=1; crc=0;
cmdeof=ineof=FALSE;
while(getcmd()==FALSE) {
if(cmd == 'a') {
cmd= 'i'; ++op1;
}
if(linno>op1) {
fprintf(stderr,"At line %d: Can't back up to %d\n",
linno, op1);
goto fubar;
}
while(linno < op1 && ineof==FALSE)
copyin();
if(crcseen && cmdcrc != crc) {
fprintf(stderr,
"CRC error on Antecedent File %u should be %u\n",
crc, cmdcrc);
fprintf(stderr,
"'%s' is not the correct Antecedent\n", aname);
if(!Ignore)
exit(1);
}
if(cmd != 'i')
while(op2-- >= linno && ineof==FALSE)
chuckline();
if(cmd=='c' || cmd=='i')
insert();
else if(cmd != 'd') {
fprintf(stderr,"Illegal command %s", cmdline);
fubar:
fprintf(stderr,
"Difference file garbled or not made by dif -e\n");
exit(1);
}
}
while(ineof == FALSE)
copyin();
fprintf(stderr,"Ssed finished\n");
close(out);
exit(0);
}
getcmd()
{
crcseen=FALSE;
if(Verbose) {
cmdcrc=0;
fprintf(stderr,"%d:", linno);
}
if(cmdeof || lgets(cmdline,xgetchar)==0) {
if(Verbose)
fprintf(stderr,"EOF on stdin\n");
return TRUE;
}
axin=cmdline;
op1=op2=getnum();
if(*axin==',') {
++axin, op2=getnum();
}
cmd=tolower(*axin++);
if(*axin++ == ' ') {
crcseen=TRUE;
cmdcrc=atoi(axin);
}
if(Verbose)
fprintf(stderr,"%sop1=%d op2=%d cmd=0%o linno=%d cmdcrc=%u\n",
cmdline, op1, op2, cmd, linno, cmdcrc);
return FALSE;
}
getnum()
{
int m;
m=0;
if(*axin=='.') {
++axin; return linno;
}
if(*axin=='$') {
++axin; return MAXINT;
}
while(isdigit(*axin))
m= (m * 10) + (*axin++ - '0');
return m;
}
copyin()
{
unsigned crck();
int len;
if((len=lgets(insline,getthis))==0) {
ineof=TRUE;
if(Verbose)
fprintf(stderr,"EOF on old file\n");
return;
}
if(fputs(insline, out)==ERROR) {
fprintf(stderr,"Write Error");
exit(1);
}
++linno;
if(--len>0)
crc += crck(insline, len, 0);
}
chuckline()
{
if(lgets(insline,getthis)==0) {
if(Verbose)
fprintf(stderr,"EOF on old file\n");
ineof=TRUE;
return;
}
}
insert()
{
for(;;) {
if(lgets(insline,xgetchar)==0) {
fprintf(stderr,"Unexpected EOF on stdin\n");
cmdeof=TRUE;
return;
}
if(insline[0]=='.' && insline[1]<=015)
return;
if(fputs(insline, out)==ERROR) {
fprintf(stderr,"Write Error");
exit(1);
}
++linno;
}
}
/* lgets returns length of line read or 0 if eof, gets rid of CR's on input! */
lgets(s, getfnx)
char *s;
int (*getfnx)();
{
int c;
char *p;
p=s;
for(;;) {
switch(c= (*getfnx)()) {
case 015:
continue;
case EOF:
case CPMEOF:
return 0;
case 012:
*p++ = c;
*p++ = 0;
return p-s;
default:
*p++ = c; continue;
}
}
}
/* *** Stuff for first translation module *** */
#define DLE 0x90
/* *** Stuff for second translation module *** */
#define SPEOF 256 /* special endfile token */
#define LARGE 30000
init_usq()
{
int i, c;
char cc;
char *p;
int numnodes; /* size of decoding tree */
char origname[14]; /* Original file name without drive */
/* Initialization */
init_cr();
init_huff();
if(getw(in)!=RECOGNIZE) {
fprintf(stderr,"%s Not Squeezed\n", aname);
exit(1);
}
/* Process rest of header */
getw(in); /* ignore checksum ... */
/* Get original file name */
p = origname; /* send it to array */
do {
*p = getc(in);
} while(*p++ != '\0');
numnodes = getw(in);
if(numnodes < 0 || numnodes >= NUMVALS) {
fprintf(stderr, "%s has invalid decode tree size\n", aname);
exit(1);
}
/* Initialize for possible empty tree (SPEOF only) */
dnode[0].children[0] = -(SPEOF + 1);
dnode[0].children[1] = -(SPEOF + 1);
/* Get decoding tree from file */
for(i = 0; i < numnodes; ++i) {
dnode[i].children[0] = getw(in);
dnode[i].children[1] = getw(in);
}
}
/* initialize decoding functions */
init_cr()
{
repct = 0;
}
init_huff()
{
bpos = 99; /* force initial read */
}
/* Get bytes with decoding - this decodes repetition,
* calls getuhuff to decode file stream into byte
* level code with only repetition encoding.
*
* The code is simple passing through of bytes except
* that DLE is encoded as DLE-zero and other values
* repeated more than twice are encoded as value-DLE-count.
*/
int
getcr()
{
int c;
if(repct > 0) {
/* Expanding a repeated char */
--repct;
return value;
} else {
/* Nothing unusual */
if((c = getuhuff()) != DLE) {
/* It's not the special delimiter */
value = c;
if(value == EOF)
repct = LARGE;
return value;
} else {
/* Special token */
if((repct = getuhuff()) == 0)
/* DLE, zero represents DLE */
return DLE;
else {
/* Begin expanding repetition */
repct -= 2; /* 2nd time */
return value;
}
}
}
}
/* Decode file stream into a byte level code with only
* repetition encoding remaining.
*/
int
getuhuff()
{
/* Follow bit stream in tree to a leaf*/
inch = 0; /* Start at root of tree */
do {
if(++bpos > 7) {
if((curin = getc(in)) == ERROR)
return ERROR;
bpos = 0;
/* move a level deeper in tree */
inch = dnode[inch].children[1 & curin];
} else
inch = dnode[inch].children[1 & (curin >>= 1)];
} while(inch >= 0);
/* Decode fake node index to original data value */
inch = -(inch + 1);
/* Decode special endfile token to normal EOF */
return (inch == SPEOF) ? EOF : inch;
}
/*
* uses algrithim of CRCK.COM previous to 5.0
*/
unsigned crck(crbuf, count, oldcrc)
char *crbuf;
unsigned oldcrc;
{
unsigned n;
while (--count >= 0) {
n= (oldcrc << 1);
n = (n & 0xFF00) | (( n + *crbuf++ ) & 0xFF);
if(oldcrc & 0x8000)
n ^= 0xA097;
oldcrc = n;
}
return oldcrc;
}